#ifndef _FIB_HEAP_
#define _FIB_HEAP_

extern "C" {
#include "fibpriv.h"	
#include "fib.h"
};

// need to extend AbstractHeapNode
// and write a int cmp_func(void* node1, void* node2)
// returning -1, 0, 1 for node1 less, equal ,greater than node2

class FibHeap;

class AbstractHeapNode {
public:
	// you can extend this class
	friend class FibHeap;
	~AbstractHeapNode() {}
private:
	struct fibheap_el* backPointer;
};

class FibHeap {
private:
	struct fibheap* m_fibheap;
public:
	FibHeap(voidcmp cmp_func): m_fibheap(fh_makeheap()) { fh_setcmp(m_fibheap, cmp_func); }

	/**
	 * It is actually a move constructor. Default copy will cause duplicated destruction
	 * TODO: Need a move constructor in std0x.
	 * @param fibh 
	 * @return 
	 */
	FibHeap(const FibHeap& fibh){
		m_fibheap = fh_makeheap();
		fh_setcmp(m_fibheap, fibh.m_fibheap->fh_cmp_fnct);
		swap(m_fibheap, (const_cast<FibHeap&>(fibh)).m_fibheap);
	}
	~FibHeap() { fh_deleteheap(m_fibheap); }
	void insert(AbstractHeapNode* element) { element->backPointer = fh_insert(m_fibheap, element); }
	AbstractHeapNode* extractMin() { return (AbstractHeapNode*)fh_extractmin(m_fibheap); }
	AbstractHeapNode* peekMin() const { return (AbstractHeapNode*)fh_min(m_fibheap); }
	void decreaseKey(AbstractHeapNode* element, AbstractHeapNode* decreasedElem) {
		decreasedElem->backPointer = element->backPointer;
		fh_replacedata(m_fibheap, element->backPointer, decreasedElem);
	}
	void remove(AbstractHeapNode* element) { fh_delete(m_fibheap, element->backPointer); }
	bool isEmpty() const { return peekMin() == NULL; }
	void clear() { while (!isEmpty()) { extractMin(); } }
};

#endif